﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Qing.Lang {

    /*
     * 这是整个语言的基本元素，Express的简写
     * 代码解析时会构建基于Expr的语法树，执行时递归求解
     * tp表示Expr的类型，作为运行期判断类型的标记
     * 通常情况下 val 对应语法元素中存放的数据，list 存放子树
     * Expr总体上分为2种，一种是值表达式，一种是语法表达式
     * 另外line存放源码中对应的行号，src表示代码的来源
     */
    public class Expr {
        public TP Tp { get; set; } = TP.None;
        public object Val { get; set; } = 0;
        public List<Expr>? List { get; set; }
        public int Line { get; set; } = 0;

        public string Src { get; set; } = "标准输入";


        public static Expr NoneExpr = new Expr();


        /*Expr的构造方法*/
        public Expr(int line=0, string src = "标准输入") {
            this.Tp = TP.None;
            this.Val = 0;
            this.Line = line;
            this.Src = src;
        }

        public Expr(TP tp, object val, int line= 0, string src = "标准输入") {
            this.Tp = tp;
            this.Val = val;
            this.Line = line;
            this.Src = src;
        }

        public Expr(TP tp, object val, List<Expr> list, int line = 0, string src = "标准输入") {
            this.Tp = tp;
            this.Val = val;
            this.List = list;
            this.Line = line;
            this.Src = src;
        }

        public Expr(Native native, int line = 0, string src = "标准输入") {
            this.Tp = TP.Native;
            this.Val = native;
            this.Line = line;
            this.Src = src;
        }

        public Expr(Func func, int line = 0, string src = "标准输入") {
            this.Tp = TP.Func;
            this.Val = func;
            this.Line = line;
            this.Src = src;
        }

        /*特殊的Expr构造方法，用来生成程序中的异常*/
        public static Expr Err(string msg, int line = 0, string src = "标准输入") {
            return new Expr(TP.Err, msg, line, src);
        }

        /*控制台打印Expr信息*/
        public void Echo() {
            //Console.WriteLine(ToStr());
            Env.LibCtx!.GetNow("@显示").Native().Run(new List<Expr> { new Expr(TP.Str, ToStr()) }, Env.LibCtx);
        }

        /*根据Expr类型的不同，转换为字符串*/
        public string ToStr(HashSet<Expr>? set = null) {
            var s = "";
            switch (Tp) {
                case TP.Err:
                    return "!!!" + Str() + "::" + Line + "行,来源：" + Src;

                case TP.None:
                    return "空";

                case TP.Var:
                    return (string)Val;

                case TP.Bool:
                    return (bool)Val ? "真" : "假";

                case TP.Bin:
                    return "0x" + Parser.ByteToHexStr(Bin());

                case TP.Int:
                    return Val.ToString()!;
                case TP.Float:
                    string fstr = Val.ToString()!;
                    if (!fstr.Contains('.')) {
                        fstr += ".0";
                    }
                    return fstr;

                case TP.Str:
                    return "“" + Parser.FormStr((string)Val) + "”";

                case TP.Args:
                case TP.Arr:
                    return ToArrStr(set);

                case TP.Paren:
                    return ToParenStr(set);

                case TP.Obj:
                    return ToObjStr(set);

                case TP.Tag:
                    return ToTagStr(set);

                case TP.Path:
                    return ToPathStr();

                case TP.Brace:
                    return ToBraceStr();

                case TP.Block:
                    return ToBlockStr();

                case TP.Func:
                    s = "@【";
                    if (Func().Asy) {
                        s = "异步 @【";
                    }
                    foreach(var item in Func().Args) {
                        s += item.ToStr() + "，";
                    }
                    foreach (var item in Func().NamedArgs) {
                        s += item.ToStr() + "，";
                    }
                    if (s.EndsWith("，")) {
                        s = s[0..(s.Length-1)];
                    }
                    s += "】｛" + Func().Desc + "｝";
                    return s;


                case TP.Op:
                    return List![0].ToStr() + (string)Val + List![1].ToStr();

                case TP.Date:
                    return Date().ToString();

                case TP.Timer:
                    return "定时器（" + Timer().Span.ToString() + "）：……。";

                case TP.Task:
                    return "异步任务：……。";

                case TP.Module:
                    return "模块：" + List![0].Str();

                case TP.Wait:
                    return "等待：……。";

                case TP.Native:
                    return "@原生函数-" + Native().Name + "｛" + Native().Desc + "｝";

                case TP.Meta:
                    return "元" + Raw().ToStr();

                default:
                    return Val.ToString()!;

            }

        }

        /*将数组类型转换为字符串*/
        public string ToArrStr(HashSet<Expr>? set) {
            if(set == null) {
                set = new HashSet<Expr> ();    
            }
            set.Add(this);
            string ret = "【";
            if (List == null || List.Count == 0) {
                return "【】";
            } else {
                for(int i=0; i<List.Count; i++) {
                    if (set.Contains(List[i])) {
                        ret += "…";
                    } else {
                        ret += List[i].ToStr(set);  
                    }
                    if (i < List.Count-1) {
                        ret += "，";
                    }
                }
                return ret + "】";
            }
        }

        /*将圆括号表达式转换为字符串*/
        public string ToParenStr(HashSet<Expr>? set) {
            if (set == null) {
                set = new HashSet<Expr>();
            }
            set.Add(this);
            string ret = "（";
            if (List == null || List.Count == 0) {
                return "（）";
            } else {
                for (int i = 0; i<List.Count; i++) {
                    if (set.Contains(List[i])) {
                        ret += "…";
                    } else {
                        ret += List[i].ToStr(set);
                    }
                    
                    if (i < List.Count-1) {
                        ret += "，";
                    }
                }
                return ret + "）";
            }
        }

        /*将对象类型转换为字符串*/
        public string ToObjStr(HashSet<Expr>? set) {
            if (set == null) {
                set = new HashSet<Expr>();
            }
            set.Add(this);
            string ret = "｛";
            object raw = Obj().Raw;
            var map = Ctx().Map;
            if (map.Count == 0) {               
                if(raw is int && (int)raw == 0) {
                    return "｛｝";
                }
                return "｛【" + Obj().Raw.ToString() + "】｝";
            } else {
                if (raw is not int || (int)raw != 0) {
                    ret += "【" + Obj().Raw.ToString() + "】，";
                }

                int i = 0;
                foreach(var entry in map) {
                    i++;
                    if (set.Contains(entry.Value)) {
                        ret += entry.Key + "：" + "…";
                    } else {
                        Expr v = entry.Value;
                        if(v.Tp == TP.Prop) {
                            v = v.Prop().Qget();
                        }
                        ret += entry.Key + "：" + v.ToStr(set);
                    }                    
                    if(i < map.Count) {
                        ret += "，";
                    }
                }
                return ret + "｝";
            }
        }

        /*将路径转换为字符串*/
        public string ToPathStr() {
            string ret = "";
            foreach(var item in List!) {
                if(item.Tp == TP.Int) {
                    ret += "#" + item.ToStr();
                } else if(item.Tp == TP.Str) {
                    ret += item.Str();
                }else {
                    ret += item.ToStr();
                }
            }
            return ret;
        }

        /*将方块转换为字符串*/
        public string ToBlockStr() {
            string ret = "【";
            for(int i = 0; i<List!.Count; i++) {
                ret += List![i].ToStr();
                if(i < List!.Count-1) {
                    ret += "，";
                }
            }
            return ret + "】";
        }

        /*将方块转换为字符串*/
        public string ToBraceStr() {
            string ret = "｛";
            for (int i = 0; i<List!.Count; i++) {
                ret += List![i].ToStr();
                if (i < List!.Count-1) {
                    ret += "，";
                }
            }
            return ret + "｝";
        }

        /*将标签类型转换为字符串*/
        public string ToTagStr(HashSet<Expr>? set) {
            if (set == null) {
                set = new HashSet<Expr>();
            }
            set.Add(this);
            string ret = "《";
            Tag tag = Tag();
            ret += tag.Name.Str() + " ";
            for(int i=0; i<tag.Attrs.Count; i++) {
                ret += tag.Attrs[i].ToStr(set);
                if(i < tag.Attrs.Count-1) {
                    ret += "，";
                }
            }
            if(tag.Children.Tp == TP.Block && tag.Children.List!.Count > 0) {
                ret += "，";
                ret += tag.Children.ToStr(set);
            }
            ret += "》";
            return ret;
        }


        /*
         * 以下是一些简化从Expr中取值的方法
         * val里存放的是object，适用于所有类型
         * 实际取值时，要根据Expr里的tp类型标记，按对应的方式取值
         */
        public byte[] Bin() {
            return (byte[])Val; //取二进制的字节数组
        }

        public bool Bool() {
            return (bool)Val; //逻辑类型取逻辑值
        }

        public char Rune() {
            return (char)Val; //取单个字符，目前没有使用
        }

        public int Int() {
            return (int)Val; //取整数值
        }

        public decimal Float() {
            return (decimal)Val; //取小数值
        }

        public char Char() {
            return (char)Val; //取单个字符，目前没有使用
        }

        public string Str() {
            return (string)Val; //取字符串
        }

        public Expr Raw() {
            return (Expr)Val; //取包装在内的Expr
        }

        public Func Func() {
            return (Func)Val; //取自定义的函数
        }

        public Native Native() {
            return (Native)Val; //取原生函数
        }

        public Ctx Ctx() {
            return (Ctx)Val; //取语境Context
        }

        public Obj Obj() {
            return (Obj)Val; //取对象
        }

        public DateTime Date() {
            return (DateTime)Val; //取日期时间
        }

        public Timer Timer() {
            return (Timer)Val; //取定时器
        }

        public Task<Expr> Task() {
            return (Task<Expr>)Val; //取任务
        }

        public Prop Prop() {
            return (Prop)Val;
        }

        public Tag Tag() {
            return (Tag)Val;
        }


        /*复制一个Expr，注意是简单复制，对集合类型只是复制引用*/
        public Expr Dup() {
            Expr ret = new Expr(Tp, Val);
            ret.List = List;
            /*if (list != null) {
                ret.list = new List<Expr>();
                foreach (var item in list!) {
                    ret.list.Add(item.Dup());
                }
            }*/
            return ret;
        }

        /*深拷贝一个Expr*/
        public Expr Clone() {
            Expr ret = Dup();
            if(Val is Obj) {
                ret.Val = new Obj(Obj().Father);
                foreach(var k in Obj().Map.Keys) {
                    ret.Obj().PutNow(k, Obj().Map[k]);
                }
            }

            if(List != null) {
                ret.List = new List<Expr>();
                foreach(var item in List!) {
                    ret.List.Add(item.Clone());
;                }
            }
            return ret;
        }

        /*将两一个Expr的内容复制到当前Expr*/
        public void Copy(Expr source) {
            Tp = source.Tp;
            Val = source.Val;
            List = source.List;
        }


        public static Expr EvalExprs(List<Expr> es, Ctx ctx) {
            bool state = true;
            return EvalExprs(es, ctx, ref state);
        }

        /*
         * 对Expr序列进行求解
         * 这是整个语言进行求解的入口
         */
        public static Expr EvalExprs(List<Expr> es, Ctx ctx, ref bool state) {
            Expr ans = new Expr(TP.None, 0);
            if(es.Count == 0) {
                return ans;
            }
            /*遍历传入的Expr序列*/
            foreach(Expr e in es) {
                if (!state) {
                    if (Env.Timers.Count>0) {
                        foreach(var item in Env.Timers) {
                            try {
                                item.Stop();
                            }catch(Exception ex) {
                                Console.WriteLine(ex.Message);
                            }
                        }
                        Env.Timers.Clear();
                    }
                    return ans;
                }
                try {
                    /*对序列中的每一个Expr进行求解，求解依赖于指定语境Context*/
                    ans = e.Eval(ctx, ref state);
                }catch(Exception execption) {
                    /*求解过程中出现异常，讲异常信息转换为Err类型的Expr*/
                    ans.Tp = TP.Err;
                    ans.Val = execption.Message;
                    ans.Line = e.Line;
                    ans.Src = e.Src;
                }

                /*求解过程一旦发现某个Expr的求解结果为Err类型，立即返回，不对后续Expr进行求解*/
                if (ans.Tp == TP.Err) {
                    if(ans.Line == 0 && e.Line != 0) {
                        ans.Line = e.Line;
                        ans.Src = e.Src;
                    }

                    return ans;
                }

                /*
                 * 求解过程一旦发现某个Expr的求解结果为Return类型，立即返回
                 * 用于自定义的函数通过返回语句提前返回结果
                 */
                if (ans.Tp == TP.Return) {
                    
                    return ans;
                       
                }

                /*
                 * 求解过程一旦发现某个Expr的求解结果为Break类型或Continue类型，立即返回
                 * 用于循环语句中进行循环控制
                 */
                if (ans.Tp == TP.Break || ans.Tp == TP.Continue) {
                    return ans;
                }
            }

            return ans;
        }



        public Expr Eval(Ctx ctx) {
            bool state = true;
            return Eval(ctx, ref state);

        }

        /*
         * 这是对每个Expr进行求解的方法
         * 根据Expr的类型和传入的语境Context求解
         * 对于值类型的Expr，可以直接返回
         * 其他类型的Expr则根据其代表的语法表达式，进行求解
         */
        public Expr Eval(Ctx ctx, ref bool state) {
            if (!state) {
                return this;
            }

            /*类型小于圆括号类型的是值类型Expr，直接返回*/
            if(Tp < TP.Var) {
                return this;
            }

            /*元类型的Expr，返回内部包装的Expr*/
            if (Tp == TP.Meta) {
                return (Expr)Val;
            }

            /*取反类型，对内部的Expr转逻辑类型后再取反*/
            if (Tp == TP.Negate) {
                return new Expr(TP.Bool, !Raw().Eval(ctx).ToBool());
            }

            /*定义类型*/
            if (Tp == TP.Dim) {
                //Raw().Val = "：";
                return Raw().Eval(ctx);
            }

            /*
             * 变量类型
             * 到当前语境Context中根据变量名查找对应的值
             * 如果值是模块类型，需先对模块求解
             */
            if (Tp == TP.Var) {
                Expr value = ctx.Get(Str());
                if (value.Tp == TP.Module) {
                    value.EvalModule(ctx);
                }
                return value;
            }

            /*函数调用类型，先查出对应的函数，再转字符串*/
            if (Tp == TP.Act) {
                return ctx.Get(Str());
            }

            /*圆括号类型，对括号内的表达式进行求解*/
            if (Tp == TP.Paren) {
                return Expr.EvalExprs(List!, ctx);
            }

            /*中括号类型，可能包含中间表达式，先求解*/
            if (Tp == TP.Block) {
                var list = new List<Expr>();
                foreach(var item in List!) {
                    if(item.Tp >= TP.Var) {
                        list.Add(item.Eval(ctx));
                    } else {
                        list.Add(item.Dup());
                    }
                }
                
                return new Expr(TP.Arr, 0, list);
            }

            /*中缀类型，根据中缀符号，进行不同方式的求解*/
            if(Tp == TP.Op) {
                return EvalOp(ctx);
            }

            /*定义函数类型，用于自定义函数，返回对应的函数类型Expr*/
            if(Tp == TP.Dim_func) {
                Expr ret = new Expr(TP.Func, 0);
                Func f = new Func(List![0].List!, List![1], ctx);
                if((int)Val == 1) {
                    f.Asy = true;
                }
                ret.Val = f;
                return ret;
            }

            /*值类型的路径，根据路径逐级查找*/
            if(Tp == TP.Path) {
                return ReducePath(List!, ctx, this);

            }

            /*调用函数类型*/
            if (Tp == TP.Call_act) {
                Expr f = ctx.Get(Str());
                if(f.Tp == TP.Native) {
                    /*如果调用的原生函数，将实参传入原生函数的Run方法*/
                    List<Expr> real = new List<Expr>();
                    List<Expr> named = new List<Expr>();
                    foreach (Expr e in List!) {
                        if (Op.IsSetOrDimOp(e)) {
                            named.Add(e);
                        } else {
                            real.Add(e.Eval(ctx));
                        } 
                    }
                    return f.Native().Run(real, ctx, null, named);
                }else if(f.Tp == TP.Func) {
                    /*如果调用的自定义函数，将实参传入自定义函数的Run方法*/
                    return f.Func().Run(List!, ctx);
                } else {
                    return Expr.Err("调用的函数不存在");
                }
            }

            /*通过路径调用函数，先根据路径找到对应的函数，再传入实参*/
            if (Tp == TP.Call_act_path) {
                Expr act = ReducePath(List!, ctx, this);
                if (act.Tp == TP.Func) {
                    List<Expr> args = (List<Expr>)Val;
                    /*val = act.Func();*/
                    return act.Func().Run(args, ctx);
                } else if (act.Tp == TP.Native) {
                    List<Expr> args = (List<Expr>)Val;
                    List<Expr> real = new List<Expr>();
                    List<Expr> named = new List<Expr>();
                    foreach (Expr e in args) {
                        if (Op.IsSetOrDimOp(e)) {
                            named.Add(e);
                        } else {
                            real.Add(e.Eval(ctx));
                        }
                    }
                    Obj? obj = null;
                    if(act.List != null && act.List.Count > 0 && act.List![0].Tp == TP.Obj) {
                        obj = act.List![0].Obj();
                    }
                    /*val = act.Native();*/
                    return act.Native().Run(real, ctx, obj, named);
                } else {
                    return Expr.Err("调用的函数不存在");
                }
                
            }

            /*大括号类型，求解后生成对象类型*/
            if(Tp == TP.Brace) {
                Obj obj = new Obj(ctx);
                Expr.EvalExprs(List!, obj);
                return new Expr(TP.Obj, obj);
            }

            /*如果，if语句*/
            if(Tp == TP.If) {
                /*
                 * list里存放的是if语句的条件和执行体
                 * 条件和执行体成对出现
                 * 如果是奇数，说明最后一次是else，默认执行
                 */
                for(int i=0; i<List!.Count; i+=2) {
                    if (List![i].Tp == TP.Brace) {
                        return Expr.EvalExprs(List![i].List!, ctx);
                    } else {
                        Expr cond = List![i].Eval(ctx);
                        if (cond.Eval(ctx).ToBool()) {
                            return Expr.EvalExprs(List![i+1].List!, ctx);
                        }
                    }

                }
                return Expr.NoneExpr;
            }

            /*当循环语句*/
            if (Tp == TP.While) {
                /*注意，循环会创建专有的语境Context*/
                Ctx wCtx = new Ctx(ctx, CtxTp.Temp);
                int i = 0;
               
                if(List!.Count == 2) {
                    /*如果list的长度为2，对应的是while语句*/
                    while (true) {
                        Expr cond = List![0].Eval(ctx);
                        if (!cond.ToBool()) {
                            break;
                        }
                        /*循环对执行体进行求解*/
                        Expr ans = Expr.EvalExprs(List![1].List!, wCtx, ref state);
                        i++;
                        /*如果单次求解的结果是Break类型，跳出循环*/
                        if(ans.Tp == TP.Break) {
                            break; 
                        }
                        /*如果单次求解的结果是Err类型或Return类型，直接返回*/
                        if (ans.Tp == TP.Err|| ans.Tp == TP.Return) {
                            return ans;
                        }

                    }
                } else {
                    /*如果list的长度为4，对应的是for语句*/
                    /*首先设置循环控制变量*/
                    List![0].Eval(wCtx);
                    while (true) {
                        /*循环开始，每次判断循环执行的条件，为真执行，为假跳出*/
                        Expr cond = List![1].Eval(wCtx);
                        if (!cond.ToBool()) {
                            break;
                        }
                        /*循环对执行体进行求解*/
                        Expr ans = Expr.EvalExprs(List![3].List!, wCtx, ref state);
                        i++;
                        /*如果单次求解的结果是Break类型，跳出循环*/
                        if (ans.Tp == TP.Break) {
                            break;
                        }
                        /*如果单次求解的结果是Err类型或Return类型，直接返回*/
                        if (ans.Tp == TP.Err|| ans.Tp == TP.Return) {
                            return ans;
                        }
                        /*单次循环结束，执行每次循环的后处理*/
                        List![2].Eval(wCtx);
                        
                    }
                }
                /*返回循环次数*/
                return new Expr(TP.Int, i);
            }

            /*执行…直到语句*/
            if(Tp == TP.Until) {
                /*注意，循环会创建专有的语境Context*/
                Ctx uCtx = new Ctx(ctx, CtxTp.Temp);
                int i = 0;
                while (true) {
                    /*开启循环，至少执行一次执行体*/
                    Expr ans = Expr.EvalExprs(List![0].List!, uCtx, ref state); 
                    i++;
                    /*如果单次求解的结果是Break类型，跳出循环*/
                    if (ans.Tp == TP.Break) {
                        break;
                    }
                    /*如果单次求解的结果是Err类型或Return类型，直接返回*/
                    if (ans.Tp == TP.Err|| ans.Tp == TP.Return) {
                        return ans;
                    }
                    /*单次执行结束，对循环判断条件进行求解*/
                    Expr cond = List![1].Eval(ctx);
                    if (cond.ToBool()) {
                        break;
                    }
                }
                /*返回循环次数*/
                return new Expr(TP.Int, i);
            }

            /*遍历语句，调用对集合遍历的方法*/
            if(Tp == TP.Foreach) {
                return EvalForeach(ctx, ref state);
            }

            /*返回语句*/
            if(Tp == TP.Return) {
                /*这里借用了list标记返回值是否已经完成求解*/
                if(List == null) {
                    /*list为null，说明返回值还未被求解过，则进行求解*/
                    return new Expr(TP.Return, Raw().Eval(ctx), new List<Expr>(0), Line, Src);
                } else {
                    /*list不为null，已求解，直接返回*/
                    return this;
                }
            }

            /*等待语句，用于等待异步任务完成*/
            if (Tp == TP.Wait) {
                Expr taskExpr = Raw().Eval(ctx);
                if(taskExpr.Tp != TP.Task) {
                    throw new Exception("等待语句只能用于等待异步任务！！！");
                }
                /*获取异步任务，等待*/
                var task = taskExpr.Task();
                task.Wait();
                return task.Result;
            }

            /*尝试...排查...例行语句，对应try...catch...finally*/
            if(Tp == TP.Try) {
                Expr tryAns;
                try {
                    /*尝试执行执行体*/
                    tryAns = EvalExprs(List![0].List!, ctx);
                } catch (Exception e) {
                    /*当执行产生异常时，创建Err类型的Expr*/
                    tryAns = Err(e.Message, Line, Src);
                }

                if (tryAns.Tp == TP.Err && List!.Count > 1 && List![1].Tp == TP.Var) {
                    /*
                     * 发现结果是Err类型
                     * 创建排查语句的语境
                     * 将异常转换为对象类型并绑定到相应的变量名
                     */
                    Ctx catchCtx = new Ctx(ctx);
                    Obj eObj = new Obj();
                    eObj.PutNow("#信息", new Expr(TP.Str, tryAns.Str()));
                    eObj.PutNow("#行", new Expr(TP.Int, tryAns.Line));
                    eObj.PutNow("#来源", new Expr(TP.Str, tryAns.Src));
                    catchCtx.PutNow(List![1].Str(), new Expr(TP.Obj, eObj));
                    /*执行排查语句的执行体*/
                    tryAns = EvalExprs(List![2].List!, catchCtx);
                } else {
                    /*如果没有发生异常，返回空*/
                    tryAns = new Expr(TP.None, 0);
                }
                if (List!.Count > 3) {
                    /*发现存在finally例行语句，执行*/
                    return EvalExprs(List![3].List!, ctx);
                }

                return tryAns;

            }

            /*抛出语句*/
            if (Tp == TP.Throw) {
                if(Raw().Tp == TP.Str) {
                    throw new Exception(Raw().Str());
                } else {
                    throw new Exception(Raw().ToStr());
                }
            }


            return this;
        }





        /*
         * 以下是对中缀类型表达式的求解
         * 具体的求解方式定义在Lang.Op中
         */
        public Expr EvalOp(Ctx ctx) {
            if (Tp != TP.Op) {
                return Expr.Err("中缀表达式语法错误");
            }

            switch (Val) {
                case "=":
                case "为":
                    return Op.SetVar(List!, ctx);

                case "：":
                case ":":
                case "设为":
                    return Op.DimVar(List!, ctx);

                case "+":
                case "加":
                    return Op.Add(List!, ctx);

                case "-":
                case "减":
                    return Op.Sub(List!, ctx);

                case "*":
                case "乘":
                    return Op.Mul(List!, ctx);

                case "/":
                case "除以":
                    return Op.Div(List!, ctx);

                case "%":
                case "模":
                    return Op.Mod(List!, ctx);


                case "**":
                    return Op.Power(List!, ctx);

                case "==":
                case "等于":
                    return Op.Eq(List!, ctx);

                case "!=":
                case "<>":
                case "不等于":
                    return Op.Ne(List!, ctx);

                case "<=":
                case "小于等于":
                    return Op.Le(List!, ctx);

                case ">=":
                case "大于等于":
                    return Op.Ge(List!, ctx);

                case "<":
                case "小于":
                    return Op.Lt(List!, ctx);

                case ">":
                case "大于":
                    return Op.Gt(List!, ctx);

                case "&&":
                case "且":
                    return Op.And(List!, ctx);

                case "||":
                case "或":
                    return Op.Or(List!, ctx);

                case "+=":
                case "加等":
                    return Op.AddSet(List!, ctx);

                case "-=":
                case "减等":
                    return Op.SubSet(List!, ctx);

                case "*=":
                case "乘等":
                    return Op.MulSet(List!, ctx);

                case "/=":
                case "除等":
                    return Op.DivSet(List!, ctx);

                case "%=":
                case "模等":
                    return Op.ModSet(List!, ctx);


            }


            return Expr.Err("中缀表达式语法错误");
        }


        /*所有的Expr都可以转换为逻辑类型*/
        public bool ToBool() {
            switch (Tp) {
                case TP.None:
                    return false; //空类型返回假
                case TP.Err:
                    return false; //异常类型返回假
                case TP.Bool:
                    return Bool(); //逻辑类型返回内部的逻辑值
                case TP.Int:
                    return Int() > 0; //整数大于0为真，小于等于0为假
                case TP.Float:
                    return Float() > 0; //小数大于0为真，小于等于0为假
                case TP.Str:
                    return Str() != ""; //空字符串为假，非空则为真
                case TP.Paren:
                    return List!.Count > 0; //圆括号类型，内部是空序列为假，否则为真
                case TP.Arr:
                    return List!.Count > 0; //数组类型，内部是空序列为假，否则为真
                case TP.Negate:
                    return !Raw().ToBool();

                default:
                    return true; //其余情况均为真
            }


        }


        /*根据Expr类型，判断是否相等*/
        public bool Eq(Expr t) {
            if (Tp == TP.None) {
                return t.Tp == TP.None;
            }

            if (Tp == TP.Int && t.Tp == TP.Float) {
                return (decimal)Int() == t.Float();
            }

            if (Tp == TP.Float && t.Tp == TP.Int) {
                return Float() == (decimal)t.Int();
            }

            if (Tp == TP.Str && t.Tp == TP.Str) {
                return Str() == t.Str();
            }

            if (Tp == TP.Arr) {
                if (t.Tp == TP.Arr) {
                    if (t.List!.Count != List!.Count) {
                        return false;
                    }
                    for (int i = 0; i<List!.Count; i++) {
                        if (!List![i].Eq(t.List![i])) {
                            return false;
                        }
                    }
                    return true;
                }
                return false;
            }

            if (Val != null && t.Val != null) {
                return Val.Equals(t.Val);
            } else {
                return Val == t.Val;
            }
        }

        /*对路径进行求解*/
        public static Expr ReducePath(List<Expr> list, Ctx ctx, Expr pathExpr) {
            Ctx currCtx = ctx; //当前语境
            Expr? currExpr = null; //当前表达式

            /*遍历整个路径列表*/
            foreach (Expr ee in list) {
                Expr e = ee;
                /*如果当前子路径是Block类型，先对子路径求值*/
                if (e.Tp == TP.Block) {
                    e = Expr.EvalExprs(e.List!, ctx);
                }

                if(currExpr == null) {
                    /*当前表达式为空，说明是在当前语境中查找值，那么路径必须是变量名*/
                    if(e.Tp == TP.Str) {
                        currExpr = currCtx.Get(e.Str());
                    } else {
                        throw new Exception("错误的路径--" + pathExpr.ToStr());
                    }
                }else if(currExpr.Tp == TP.Obj) {
                    /*当前表达式为对象类型，说明是在对象中查找值，那么路径必须是变量名*/
                    if (e.Tp == TP.Str) {
                        currExpr = currCtx.Get(e.Str());

                        if(currExpr.Tp == TP.None) {
                            throw new Exception("错误的路径--" + pathExpr.ToStr());
                        }

                    } else {
                        throw new Exception("错误的路径--" + pathExpr.ToStr());
                    }

                    if(currExpr.Tp == TP.Prop) {
                        currExpr = currExpr.Prop().Qget();
                    }

                }else if(currExpr.Tp == TP.Arr) {
                    /*当前表达式为数组类型，说明是在数组中获取值*/
                    Expr idx = e.Clone();
                    if(e.Tp == TP.Str) {
                        /*
                         * 当前路径是字符串类型，那么可能是对应的变量
                         * 先进行求解，可能得到索引序号
                         */
                        idx = currCtx.Get(e.Str());
                    }

                    /*获取数组中的元素，必须是整数类型的索引序号*/
                    if(idx.Tp == TP.Int) {
                        /*进行边界检查*/
                        if (idx.Int() < 0 || idx.Int() >= currExpr!.List!.Count) {
                            throw new Exception("路径下标越界--"+ pathExpr.ToStr());
                        } else {
                            currExpr = currExpr!.List![idx.Int()];
                        }
                    }else {
                        throw new Exception("错误的路径--" + pathExpr.ToStr());
                    }

                }else if(currExpr.Tp == TP.Str) {
                    /*当前表达式为字符串类型，说明是在字符串中获取字符*/
                    Expr idx = e.Clone();
                    if (e.Tp == TP.Str) {
                        /*
                         * 当前路径是字符串类型，那么可能是对应的变量
                         * 先进行求解，可能得到索引序号
                         */
                        idx = currCtx.Get(e.Str());
                    }
                    /*获取字符串中的字符，必须是整数类型的索引序号*/
                    if (idx.Tp == TP.Int) {
                        /*进行边界检查*/
                        if (idx.Int() < 0 || idx.Int() >= currExpr!.Str().Length) {
                            throw new Exception("路径下标越界--" + pathExpr.ToStr());
                        } else {
                            currExpr = new Expr(TP.Str, currExpr!.Str()[idx.Int()].ToString());
                        }
                    }else {
                        throw new Exception("错误的路径--" + pathExpr.ToStr());
                    }

                }else if(currExpr.Tp == TP.Func) {
                    if(e.Tp == TP.Args) {
                        currExpr = currExpr.Func().Run(e.List!, ctx);

                    } else {
                        throw new Exception("错误的路径内函数调用--"+ pathExpr.ToStr());
                    }

                } else if(currExpr.Tp == TP.Native) {
                    /*
                 * 如果当前Expr是原生函数，且当前的语境不为空，说明是在对象里调用原生函数
                 * 把当前对象作为原生函数的参数传入Run方法
                 */
                    if (currCtx != ctx) {
                        currExpr.List = new List<Expr> { new Expr(TP.Obj, (Obj)currCtx!) };
                    }

                    if(e.Tp == TP.Args) {
                        List<Expr> real = new List<Expr>();
                        List<Expr> named = new List<Expr>();
                        foreach (Expr arg in e.List!) {
                            if (Op.IsSetOrDimOp(arg)) {
                                named.Add(arg);
                            } else {
                                real.Add(arg.Eval(ctx));
                            }   
                        }
                        if(currExpr.List != null && currExpr.List!.Count > 0) {
                            currExpr = currExpr.Native().Run(real, currCtx, currExpr.List![0].Obj(), named);
                        } else {
                            currExpr = currExpr.Native().Run(real, currCtx, null, named);
                        }
                    } else {
                        throw new Exception("错误的路径--"+ pathExpr.ToStr());
                    }
                } else {
                    throw new Exception("错误的路径--"+ pathExpr.ToStr());
                }

                if(currExpr.Tp == TP.Module) {
                    currExpr = currExpr.EvalModule(ctx);
                }

                if (currExpr.Tp == TP.Obj) {
                    /*当前Expr是对象类型，那么要把语境切换到对象内*/
                    currCtx = currExpr.Obj();
                }
            }

            return currExpr!;
        }


        /*遍历集合类型Expr*/
        public Expr EvalForeach(Ctx ctx, ref bool state) {
            int times = 0;
            Expr coll = List![0].Eval(ctx, ref state);
            Expr item = List![1];

            Ctx fCtx = new Ctx(ctx, CtxTp.Temp);
            if(coll.Tp == TP.Arr) {
                /*对于数组类型，把列表里的每个Expr绑定到迭代变量*/
                foreach(Expr e in coll.List!) {
                    fCtx.PutNow(item.Str(), e);
                    Expr ans = Expr.EvalExprs(List![2].List!, fCtx, ref state);
                    times++;
                    if (ans.Tp == TP.Break) {
                        break;
                    }
                    if (ans.Tp == TP.Err || ans.Tp == TP.Return) {
                        return ans;
                    }
                }
            }else if(coll.Tp == TP.Str) {
                /*对于字符串类型，把字符串里的每个字符生成新的字符串Expr，再绑定到迭代变量*/
                string str = coll.Str();
                for(int i=0; i<str.Length; i++) {
                    fCtx.PutNow(item.Str(), new Expr(TP.Str, str[i].ToString()));
                    Expr ans = Expr.EvalExprs(List![2].List!, fCtx, ref state);
                    times++;
                    if (ans.Tp == TP.Break) {
                        break;
                    }
                    if (ans.Tp == TP.Err || ans.Tp == TP.Return) {
                        return ans;
                    }
                }
            }else if(coll.Tp == TP.Obj) {
                foreach(var k in coll.Obj().Map.Keys) {
                    /*对于字符串类型，把键值对生成新的数组Expr，再绑定到迭代变量*/
                    Expr Entry = new Expr(TP.Arr, 0, new List<Expr>());
                    Entry.List!.Add(new Expr(TP.Str, k));
                    Entry.List!.Add(coll.Obj().Map[k]);
                    fCtx.PutNow(item.Str(), Entry);
                    Expr ans = Expr.EvalExprs(List![2].List!, fCtx, ref state);
                    times++;
                    if (ans.Tp == TP.Break) {
                        break;
                    }
                    if (ans.Tp == TP.Err || ans.Tp == TP.Return) {
                        return ans;
                    }
                }
            } else {
                return Expr.Err("遍历语句只适用与集合类型", Line, Src);
            }


            return new Expr(TP.Int, times);
        }


        //模块生成对象
        public Expr EvalModule(Ctx ctx) {
            /*变量对应的是模块类型，先求解，生成对象类型*/
            Ctx moduleCtx = new Obj(Env.LibCtx);
            string moduleName = List![0].Str();

            string originDir = "";
            if (!moduleName.StartsWith("http")) {
                originDir = Directory.GetCurrentDirectory();
                FileInfo fi = new FileInfo(moduleName);
                string dir = fi.DirectoryName!;
                Directory.SetCurrentDirectory(dir);
            }

            Expr.EvalExprs(new Parser().Parse(List![1].Str(), moduleCtx, moduleName), moduleCtx);

            if (originDir != "") {
                Directory.SetCurrentDirectory(originDir);
            }

            Tp = TP.Obj;
            Val = moduleCtx;
            /*模块是全局唯一的，根据模块名，存放到模块记录表里*/
            Env.ModuleMap[moduleName] = this;
            return this;
        }



    }



}
